﻿Imports System.IO
Imports MailKit.Net.Smtp
Imports System.Text
Imports System.Text.Json
Imports System.Windows.Forms
Imports BrowserCollect
Imports Common
Imports Sy.Data
Imports System.Threading
Imports DnsClient

Public Class JsObject
    Public Shared ReadOnly Property Instance As JsObject = New JsObject
    Public Sub New()
        CollectScriptFactory.Instance.Register(New Common.GoogleMapPlaceCollectScript())
        CollectScriptFactory.Instance.Register(New Common.GoogleMapSearchCollectScript())
    End Sub
#Region "Form"
    Public Function ChangeSize() As Integer
        Return Frm_Main.Instance.InvokEx(Function() Frm_Main.Instance.ChangeSize())
    End Function
    Public Sub MinSize()
        Frm_Main.Instance.InvokEx(Sub() Frm_Main.Instance.MinSize())
    End Sub
    Public Sub SetCloseButtonVisible(v As Boolean)
        Frm_Main.Instance.Invoke(Sub() Frm_Main.Instance.SetCloseButtonVisible(v))
    End Sub
    Public Sub Drag()
        Frm_Main.Instance.InvokEx(Sub() Frm_Main.Instance.FormDrag1.InvokeDrag())
    End Sub
    Public Sub [Exit]()
        MainForm.InvokEx(Sub()
                             Try
                                 MainForm.Hide()
                             Catch ex As Exception
                             End Try
                         End Sub)
        EndTask.Invoke()
    End Sub
    Public Sub ShowDebugButton() 'Erp3
        Frm_Main.Instance.Invoke(Sub() Frm_Main.Instance.ShowDebugButton())
    End Sub
#End Region
#Region "Auth"
    Public Function Auth(Url As String) As String
        Dim TokenUrl = ""
        MainForm.InvokEx(Sub()
                             'Auth = Frm_Auth.ShowDialog(Url)
                             Dim Frm_Auth As New Frm_Auth
                             TokenUrl = Frm_Auth.ShowDialog(Url)
                         End Sub)
        If TokenUrl.IsNullOrEmpty() Then Return CommonInvoke.Instance.GetReslut(False, Null)
        Return CommonInvoke.Instance.GetReslut(True, TokenUrl)
    End Function
#End Region
#Region "Data"
    ''' <summary>
    ''' 国家列表Post UILog需要补充完善
    ''' </summary>
    ''' <returns></returns>
    Public Function DataSearchNation() As String
        Try
            Dim Location As ResultItem() = ResultItem.Load()
            Dim Json = JsonObject.Serialize(Location)
            Return CommonInvoke.Instance.GetReslut(True, Json)
        Catch ex As Exception
            Return CommonInvoke.Instance.GetReslut(False, $"读取数据库失败,失败原因:{ex.Message}")
        End Try
    End Function
    ''' <summary>
    ''' Google相关关键词 = 0
    ''' Yahoo相关关键词 = 1
    ''' Baidu相关关键词 = 2
    ''' </summary>
    ''' <param name="keyword"></param>
    ''' <param name="channel"></param>
    ''' <returns></returns>
    Public Function ExpandKeywords(keyword As String, channel As Integer) As String
        Dim Log As LogSub = Null
        Log = GetLoger(Log)
        If channel > 2 Then Return CommonInvoke.Instance.GetReslut(False, "网站类型有误")
        Dim Url = CommonInvoke.Instance.GetUrlByID(keyword, channel)
        Dim Encoding = System.Text.Encoding.UTF8
        If channel = 2 Then Encoding = System.Text.Encoding.Default
        Dim html As Sy.String = Sy.Net.Factory.Http(Url).SetEncoding(Encoding).Get()
        If html.IsNotEmpty Then
            Log("新增关键词如下:")
            Dim Keywords = CommonInvoke.Instance.GetKeywordsByID(keyword, channel, html)
            Return CommonInvoke.Instance.GetReslut(True, JsonObject.Serialize(Keywords))
        Else
            Return CommonInvoke.Instance.GetReslut(False, "拓展关键词失败")
        End If
    End Function
    ''' <summary>
    ''' 搜索域名
    ''' </summary>
    ''' <returns></returns>
    Public Function DataSearchDomain(nations As String(), keywords As String) As String
        Dim Log As LogSub = Null
        Log = GetLoger(Log)
        Dim OutPut As New Dictionary(Of String, List(Of SERPMasterResponse.ResultsItem.ContentItem.ResultsItem.OrganicItem))
        For Each nation In nations
            If OutPut.ContainsKey(nation) Then Continue For
            Dim Location As ResultItem() = ResultItem.LoadWhere(nation)
            If Location.IsNotNull() AndAlso Location.Count() > 0 Then
                Dim Area = Location.First()
                Log($"正在获取[{Area.geo_name_CN}]地区数据...")
                Dim url = $"https://rt.serpmaster.com/?q={Sy.Text.Encode.Url_Encode(keywords)}&parse=true&num=100&geo={Area.geo_name}"
                Dim html = Sy.Net.Factory.Http("http://httpproxy.miwaimao.com/").SetHeader("ProxyUrl", url).SetHeader("SerpmasterKey", "True").Get()
                Dim Response As SERPMasterResponse = SERPMasterResponse.DeserializeSafety(html)
                If Response.IsNull() Then
                    Log($"[{Area.geo_name_CN}]获取数据失败!")
                    Continue For
                ElseIf Response.results.IsNull() OrElse Response.results.Count = 0 OrElse Response.results(0).content.IsNull() OrElse Response.results(0).content.results.IsNull() OrElse Response.results(0).content.results.organic.IsNull() OrElse Response.results(0).content.results.IsNull() OrElse Response.results(0).content.results.organic.Count = 0 Then
                    Log($"[{Area.geo_name_CN}]未获取到数据!")
                    Continue For
                End If
                OutPut.Add(nation, Response.results(0).content.results.organic)
            Else
                Continue For
            End If
        Next
        If OutPut.Count = 0 Then Return CommonInvoke.Instance.GetReslut(False, "获取数据失败!")
        Dim Json = JsonObject.Serialize(OutPut)
        Return CommonInvoke.Instance.GetReslut(True, Json)
    End Function
    ''' <summary>
    ''' 搜索邮箱
    ''' </summary>
    ''' <param name="domains"></param>
    ''' <returns></returns>
    Public Function DataSearchEmail(domains As String()) As String
        Dim Log As LogSub = Null
        Log = GetLoger(Log)
        Dim OutPut As New Dictionary(Of String, List(Of DomainSearchResponse.EmailsItem))
        Dim ErrMessage As String = ""
        For Each domain In domains
            If OutPut.ContainsKey(domain) Then Continue For
            Log($"正在获取域名为{domain}邮箱信息...")
            '2.获取邮箱详细信息
            Dim URL = $"https://api.minelead.io/v1/search/?domain={domain}"
            Dim html = Sy.Net.Factory.Http("http://httpproxy.miwaimao.com/").SetHeader("ProxyUrl", URL).SetHeader("MineleadKey", "True").Get()
            '{"domain": "outdoorgearlab.com", "status": "not found"}
            Dim DSresponse As DomainSearchResponse = DomainSearchResponse.DeserializeSafety(html)
            If DSresponse.IsNull() Then
                Log("获取邮箱详细信息失败!")
                Continue For
            ElseIf DSresponse.emails.IsNull() Then
                If DSresponse.status.IsNotWhiteSpace() Then
                    Log($"该域名下无有效邮箱!原因:{DSresponse.status}")
                    If ErrMessage.Length > 0 Then ErrMessage += vbCrLf
                    ErrMessage += $"[{domain}]失败原因:{DSresponse.status}]"
                    Continue For
                Else
                    Log($"该域名下无有效邮箱!")
                End If
                Continue For
            End If
            OutPut.Add(domain, DSresponse.emails)
        Next
        If OutPut.Count = 0 Then Return CommonInvoke.Instance.GetReslut(False, $"获取邮箱详细信息失败{vbCrLf}{ErrMessage}")
        Dim Json = JsonObject.Serialize(OutPut)
        Return CommonInvoke.Instance.GetReslut(True, Json)
    End Function
#End Region
#Region "客户"
    ''' <summary>
    ''' 导入客户数据
    ''' </summary>
    ''' <returns></returns>
    Public Function ImportClient() As String
        MainForm.Invoke(Sub() Frm_ImportClient.ShowDialog(MainForm))
        '刷新UI
        ScriptManager.Instance.RefreshCLientUI()
        Return CommonInvoke.Instance.GetReslut(True, "")
    End Function
    Public Function ExportClient(Ids As Integer()) As String
        MainForm.InvokEx(Sub() Frm_ExportClient.ShowDialog(Ids))
        Return CommonInvoke.Instance.GetReslut(True, "")
    End Function
#End Region
#Region "Email Event"
    Private CurCount As Integer
    Private _runningTasks As New List(Of Integer)
    Private _runningThread As Threading.Thread

    Private Function DeserializeSafety(Of T)(json As String)
        Try
            Return System.Text.Json.JsonSerializer.Deserialize(Of T)(json)
        Catch ex As Exception
            Debug.Print(ex.ToString())
            Return Null
        End Try
    End Function

    ''' <summary>
    ''' 发送邮件
    ''' </summary>
    ''' <param name="Sender">发件人Json数据</param>
    ''' <param name="Rever">收件人Json数据</param>
    ''' <param name="Content">发件内容Json数据</param>
    ''' <param name="contentSettings">发件内容配置数据</param>
    ''' <param name="MinInterval">最小间隔时间</param>
    ''' <param name="MaxInterval">最大间隔时间</param>
    ''' <param name="RandName">昵称</param>
    ''' <param name="SendMode">发送模式：HTTP=0, SMTP=1, MOBILE=2</param>
    ''' <param name="SendCount">单个发件箱最大发送数量限制</param>
    ''' <param name="AllCount">总发送数量限制</param>
    ''' <param name="OnceTimeMuti">是否设置单次邮件发送数量限制</param>
    ''' <param name="OnceTimeNum">单次邮件发送数量限制</param>
    ''' <param name="ReplyTo"></param>
    ''' <param name="OpenADSL">是否设置全局ADSL拨号设置</param>
    ''' <param name="ADSL_Count">ADSL连续发送数量限制</param>
    ''' <param name="ADSL_EN">宽带名称</param>
    ''' <param name="ADSL_U">用户名</param>
    ''' <param name="ADSL_P">密码</param>
    ''' <param name="OpenSIM7600">是否启用全局设备换IP</param>
    ''' <returns></returns>
    Public Function SendEmail(Sender As String, Rever As String, ContentList As List(Of String), contentSettings As String, MinInterval As Integer, MaxInterval As Integer, RandName As String, SendMode As EnumSendMode, SendCount As Integer, AllCount As Integer, OnceTimeMuti As Boolean, OnceTimeNum As Integer, ReplyTo As String, OpenADSL As Boolean, ADSL_Count As Integer, ADSL_EN As String, ADSL_U As String, ADSL_P As String, OpenSIM7600 As Boolean, marketingTaskId As Integer, marketingTaskName As String, sendSettingStr As String) As String
        If _runningTasks.Contains(marketingTaskId) Then
            Return CommonInvoke.Instance.GetReslut(True, "正在运行中")
        End If
        _runningTasks.Add(marketingTaskId)
        Dim Content = String.Join("", ContentList)
        Dim ReportSend As New List(Of ReportSendEmail)
        Dim Log As LogSub = Null
        Log = GetLoger(Log)

        Dim lst_Sender As List(Of SenderInfo) = JsonObject.DeserializeSafety(Of List(Of SenderInfo))(Sender)
        Dim lst_Rev As List(Of ReverInfo) = JsonObject.DeserializeSafety(Of List(Of ReverInfo))(Rever)
        Dim lst_Content As List(Of Cls_Content) = DeserializeSafety(Of List(Of Cls_Content))(Content)
        Dim settings As List(Of ContentSettings) = JsonObject.DeserializeSafety(Of List(Of ContentSettings))(contentSettings)
        Dim sendSettings As SendSetting = JsonObject.DeserializeSafety(Of SendSetting)(sendSettingStr)
        sendSettings = If(sendSettings.IsNull(), New SendSetting(), sendSettings)
        If lst_Sender.IsNull OrElse lst_Sender.Count = 0 OrElse lst_Rev.IsNull OrElse lst_Rev.Count = 0 OrElse lst_Content.IsNull OrElse lst_Content.IsNothing OrElse lst_Content.Count = 0 Then
            Return CommonInvoke.Instance.GetReslut(False, "发送邮件失败:发件人/收件人/内容信息获取出错")
        End If
        _runningThread = New Threading.Thread(
            New Threading.ThreadStart(
            Sub()
                Dim HTTPS As Integer, HTTPF As Integer, SMTPS As Integer, SMTPF As Integer, MobileS As Integer, MobileF As Integer
                Dim Sim7600_Count As Integer
                Dim Cur = 0
                Dim statustxt As String = ""
                '当前轮询发送次数
                Dim CurOnce = 1
                Dim i = 0
                Dim lastLogGuid = Guid.Empty
                Do
                    i += 1
#Region "判断是否发完"
                    If OnceTimeMuti Then
                        If OnceTimeNum > SendCount Then
                            Log("警告:单次邮件数大于单个发件箱最大发送数量限制")
                            Exit Do
                        End If
                    End If
                    If i > AllCount Then
                        Log("提示:已经达到最大总发送数量！")
                        Exit Do
                    End If
                    Dim Rev As String
                    If lst_Sender.Count <= 0 Then
                        Log($"提示:请先添加发件邮箱！")
                        Exit Do
                    End If
                    If lst_Rev.Count <= 0 Then
                        Log($"提示:所有收件箱已发完！")
                        Exit Do
                    Else
                        Rev = lst_Rev(0).Mail
                    End If
#End Region
#Region "Info"
                    '发件人信息
                    Dim CurSender As SenderInfo
                    If sendSettings.SendMethod = EnumSendMethod.Random Then
                        Dim availableSenders = lst_Sender.Where(Function(s) s.AllCount < SendCount).ToArray()
                        If availableSenders.Length = 0 Then
                            Log($"提示:发件箱都已经达到最大发送数量！")
                            Exit Do
                        End If
                        Dim randIndex = Rand.Next(availableSenders.Length)
                        CurSender = lst_Sender(randIndex)
                    Else
                        If Cur >= lst_Sender.Count Then Cur = 0
                        CurSender = lst_Sender(Cur)
                        '判断当前发件人发送数量来选择发件人(轮询中发送次数)
                        If OnceTimeMuti Then
                            If CurOnce >= OnceTimeNum Then
                                Cur += 1
                                CurOnce = 1
                            End If
                        Else
                            Cur += 1
                        End If
                        CurOnce += 1
                        '判断当前发件人最大发送个数 所有超过则退出
                        If CurSender.AllCount >= SendCount Then
                            'Form.MsgBox.Show($"发件箱都已经达到最大发送数量！", "确定", "提示")
                            'Exit Do
                            Dim TempSenderLst = lst_Sender.Skip(Cur + 1).ToList()
                            '追加到末尾
                            TempSenderLst.AddRange(lst_Sender.Take(Cur + 1))
                            Dim IsHaveSender = False
                            '遍历查询是否还要可发送邮箱
                            For Each SenderItem In TempSenderLst
                                Cur += 1
                                If SenderItem.AllCount < SendCount Then
                                    IsHaveSender = True
                                    Exit For
                                End If
                            Next
                            If IsHaveSender Then
                                If Cur >= lst_Sender.Count Then Cur -= lst_Sender.Count
                                CurSender = lst_Sender(Cur)
                                If Not OnceTimeMuti Then Cur += 1
                                CurOnce = 2
                            Else
                                Log($"提示:发件箱都已经达到最大发送数量！")
                                Exit Do
                            End If
                        End If
                    End If
                    '发件内容
                    Dim Conten As Cls_Content
                    If sendSettings.SendTemplateMethod = EnumSendMethod.Random Then
                        Conten = lst_Content(Rand.Next(lst_Content.Count))
                    Else
                        Conten = lst_Content(i Mod lst_Content.Count)
                    End If
                    '收件人信息
                    Dim RevNick = lst_Rev(0).MailNick
                    Dim Ra = lst_Rev(0).Mail
                    Dim SendName As String
                    Dim Sa = CurSender.Account
                    Dim setting = settings.FirstOrDefault()
                    If RandName.Trim.Length > 0 Then
                        SendName = RandName
                    Else
                        SendName = CurSender.Account
                    End If
                    Dim SendTitle = Cls_Content.ReplaceWord(Conten?.Title, Sa, SendName, Ra, RevNick)
                    Dim SendContent = Cls_Content.ReplaceWord($"{Conten?.Content}{(If(Not sendSettings.TrackReadStatus OrElse setting.IsNull() OrElse setting.ReadUrl.IsNullOrEmpty(), String.Empty, $"<img src=""{setting.ReadUrl}"">"))}", Sa, SendName, Ra, RevNick)
#End Region
#Region "发送邮件"
                    Dim R As Boolean = False
                    Dim MailType As MailType = If(CurSender.MailType, MailType.Empty)
                    Dim Exp As Exception = Nothing
                    _runningLock.Wait()
                    Select Case SendMode
                        Case EnumSendMode.SMTP
#If debug Then
                            Dim ran = Rand.Next(2)
                            R = ran > 0
                            If Not R Then
                                Exp = New Exception("异常aaaaaaaaaaa")
                            End If
#Else
                            R = Sy.UI.Email.SendSmtpMail(MailType.Smtp,
                                                                     MailType.Port,
                                                                     CurSender.Account,
                                                                     CurSender.Password,
                                                                     SendTitle,
                                                                     SendContent, True,
                                                                     New List(Of String)({Rev}),
                                                                     RandName,,
                                                                     Conten?.FilePath,
                                                                     Nothing,
                                                                     MailType.SSL,
                                                                     ReplyTo,
                                                                     Exp)
#End If

                            If R Then
                                SMTPS += 1
                                statustxt = " 成功"
                            Else
                                SMTPF += 1
                                statustxt = $" 失败[{Exp.Message}]"
                            End If
                    'Invoke(Sub()
                    '           Log(CurSender.Account & " 发送至 " & Rev & statustxt)
                    '           GroupBox10.Text = I18N.Instance.GroupBox10(SMTPS, SMTPF) ' "当前共发送成功:" & SMTPS & ",失败:" & SMTPF
                    '       End Sub)
                        Case EnumSendMode.HTTP
                            If CurSender.Account.ToLower.EndsWith("@126.com") Then
                                R = Sy.Net.Mail.Send126webmail(CurSender.Account,
                                                               CurSender.Password,
                                                               RandName,
                                                               Rev,
                                                               SendTitle,
                                                               True,
                                                               SendContent)
                            ElseIf CurSender.Account.ToLower.EndsWith("@163.com") Then
                                R = Sy.Net.Mail.Send163webmail(CurSender.Account,
                                                                           CurSender.Password,
                                                                           RandName,
                                                                           Rev,
                                                                           SendTitle,
                                                                           True,
                                                                           SendContent)
                            Else
                                R = Sy.Net.Mail.Send163QYwebmail(CurSender.Account,
                                                                             CurSender.Password,
                                                                             RandName,
                                                                             {Rev}.ToList,
                                                                             SendTitle,
                                                                             True,
                                                                             SendContent,
                                                                             Conten.FilePath,
                                                                             Nothing,
                                                                             Log)
                            End If
                            If R Then
                                HTTPS += 1
                                statustxt = " 成功"
                            Else
                                HTTPF += 1
                                statustxt = " 失败"
                            End If
                    'Invoke(Sub()
                    '           Log(CurSender.Account & " 发送至 " & Rev & statustxt)
                    '           GroupBox10.Text = I18N.Instance.GroupBox10(HTTPS, HTTPF) '"当前共发送成功:" & HTTPS & ",失败:" & HTTPF
                    '       End Sub)
                        Case EnumSendMode.MOBILE
                            R = Sy.Net.Mail.SendSmtpMail(MailType.Smtp,
                                                                     MailType.Port,
                                                                     CurSender.Account,
                                                                     CurSender.Password,
                                                                     SendTitle,
                                                                     SendContent, True,
                                                                     Rev,
                                                                     RandName, "",
                                                                     Conten?.FilePath,
                                                                     Nothing,
                                                                     MailType.SSL,
                                                                     ReplyTo,
                                                                     Exp)
                            If R Then
                                MobileS += 1
                                statustxt = " 成功"
                            Else
                                MobileF += 1
                                statustxt = $" 失败[{Exp.Message}]"
                            End If
                            'Invoke(Sub()
                            '           Txt_Log.Text = Txt_Log.Text & CurSender.Account & " 发送至 " & Rev & statustxt & vbCrLf
                            '           GroupBox10.Text = I18N.Instance.GroupBox10(MobileS, MobileF) '"当前共发送成功:" & MobileS & ",失败:" & MobileF
                            '       End Sub)
                    End Select
#End Region
#Region "发送结果及使用IP情况"
                    Dim State As SendState
                    Dim rrr = lst_Rev(0)
                    rrr.SendTime = Now
                    If R Then
                        rrr.SendCount += 1
                        CurSender.SuccessCount += 1
                        State = SendState.Success
                    Else
                        CurSender.FailCount += 1
                        lst_Rev.Remove(lst_Rev(0))
                        State = SendState.Fail
                    End If
                    'rrr.Edt()
                    CurSender.AllCount += 1
                    CurSender.LastSendTime = Now
                    'CurSender.Edt()
                    lst_Rev.Remove(rrr)
                    settings.Remove(settings(0))
                    CurCount += 1
                    If OpenADSL Then
                        Log($"当前IP已经使用{CurCount}次")
                        If CurCount >= ADSL_Count Then
                            CheckIP(Sy.Cmd.ChangeIP(ADSL_EN, ADSL_U, ADSL_P, Log, 1000), Log)
                            CurCount = 0
                        End If
                    End If
                    If OpenSIM7600 Then
                        'Invoke(Sub() Log($"当前IP已经使用{CurCount}次{vbCrLf }"))
                        If CurCount >= Sim7600_Count Then
                            Log($"正在切换IP{vbCrLf }")
                            If Sy.Device.SIM7600CE.Instance.ModifyIP(120) Then
                                Log($"切换IP完成 IP：{Sy.Device.SIM7600CE.Instance.CurIP}{vbCrLf }")
                            Else
                                Log($"切换IP失败 {vbCrLf }")
                                Log($"{Sy.Device.SIM7600CE.Instance.ErrInfo}{vbCrLf }")
                                Exit Do
                            End If
                            CurCount = 0
                        End If
                    End If
#End Region
                    Dim Complete As Boolean = False
                    If OnceTimeMuti Then
                        If OnceTimeNum > SendCount Then Complete = True
                    End If
                    If i + 1 > AllCount Then Complete = True
                    If lst_Sender.Count <= 0 Then Complete = True
                    If lst_Rev.Count <= 0 Then Complete = True
                    Dim errorMsg = If(Exp.IsNotNull, Exp.Message, "")
                    Dim ReportSendEmail As New ReportSendEmail(Rev, CurSender.Account, State, marketingTaskId, marketingTaskName, Complete, i = 1, errorMsg, Conten.Id, Conten.Title)
                    Dim Json = JsonObject.Serialize(ReportSendEmail)
                    ScriptManager.Instance.ReportSendEmail(Json)
                    Dim completedMessage = If(Exp.IsNotNull,
                        VueLog.FlushFailed(lastLogGuid, $"[{ReportSendEmail.MarketingTaskName}#{ReportSendEmail.Source}] {ReportSendEmail.SenderEmail}向{ReportSendEmail.ReceiverEmail}发送邮件[{ReportSendEmail.TemplateName}]失败: {ReportSendEmail.ErrorMsg}", ReportSendEmail),
                        VueLog.FlushInfo(lastLogGuid, $"[{ReportSendEmail.MarketingTaskName}#{ReportSendEmail.Source}] {ReportSendEmail.SenderEmail}向{ReportSendEmail.ReceiverEmail}发送邮件[{ReportSendEmail.TemplateName}]成功", ReportSendEmail))
                    ScriptManager.Instance.LogSendEmail(JsonObject.Serialize(completedMessage))
                    If Complete Then
                        _runningTasks.Remove(marketingTaskId)
                        Exit Do
                    End If
                    Dim sendInterval = RND.Next(MinInterval, MaxInterval + 1)
                    Dim waitMessage = VueLog.Info($"正在模拟的人工发送中，{sendInterval}秒后将发送下一个邮件", countdown:=sendInterval)
                    lastLogGuid = waitMessage.id
                    ScriptManager.Instance.LogSendEmail(JsonObject.Serialize(waitMessage))
                    Threading.Thread.Sleep(sendInterval * 1000)
                Loop
            End Sub))
        _runningThread.Start()
        Return CommonInvoke.Instance.GetReslut(True, "")
    End Function

    Public Function RunningTasks() As String
        Return CommonInvoke.Instance.GetReslut(True, $"[{String.Join(",", _runningTasks)}]")
    End Function

    Private _runningLock As New ManualResetEventSlim(True)
    Public Function PauseSendEmail() As String
        _runningLock.Reset()
        Return CommonInvoke.Instance.GetReslut(True, "")
    End Function
    Public Function ResumeSendEmail() As String
        _runningLock.Set()
        Return CommonInvoke.Instance.GetReslut(True, "")
    End Function

    Public Function IsPaused() As String
        Return CommonInvoke.Instance.GetReslut(True, (Not _runningLock.IsSet).ToString().ToLower())
    End Function

    Public Function AbortSendEmail() As String
        _runningThread.Abort()
        _runningLock.Set()
        _runningTasks.Clear()
        Return CommonInvoke.Instance.GetReslut(True, "")
    End Function

    Public Function VerifySmtp(host As String, port As Integer, useSsl As Boolean, username As String, password As String) As String
        Dim smtpClient = New SmtpClient()
        Dim result = True
        Dim msg = ""
        Try
            smtpClient.Connect(host, port, useSsl)
            smtpClient.Authenticate(username, password)
            smtpClient.Disconnect(True)
        Catch ex As Exception
            msg = ex.Message
            result = False
        End Try
        smtpClient.Dispose()
        Return CommonInvoke.Instance.GetReslut(result, msg)
    End Function

    Dim Lst_Pool As List(Of String)
    Private Sub CheckIP(ip As String, Log As LogSub)
        If ip.Length > 0 Then
            If Lst_Pool.Contains(ip) Then
                Log("重复IP")
            Else
                Lst_Pool.Add(ip)
                Log($"新的IP 当前IP数量：{Lst_Pool.Count}")
            End If
        End If
    End Sub
    ''' <summary>
    ''' 验证邮箱
    ''' </summary>
    ''' <param name="Email"></param>
    ''' <returns></returns>
    Public Function VerifyEmail(Email As String) As String
        If Email.IsNull() OrElse Email.Length = 0 Then CommonInvoke.Instance.GetReslut(False, "[邮箱错误]无法验证邮箱")
        Dim Thread As New Threading.Thread(
            New Threading.ThreadStart(
            Sub()
                Dim Result As New Dictionary(Of String, Boolean)
                Dim url As String = $"https://api.minelead.io/v1/validate/?email={Email}"
                Dim html As String = Sy.Net.Factory.Http("http://httpproxy.miwaimao.com/").SetHeader("ProxyUrl", url).SetHeader("MineleadKey", "True").Get()
                Dim response As VerifyEmailResponse = VerifyEmailResponse.DeserializeSafety(html)
                If response.IsNull() OrElse response.status.IsNull() OrElse Not response.status = "success" Then
                    Result.Add(Email, False)
                Else
                    Result.Add(Email, response.webmail)
                End If
                ScriptManager.Instance.VerifyEmail(JsonObject.Serialize(Result))
            End Sub))
        Thread.Start()
        Return CommonInvoke.Instance.GetReslut(True, "")
    End Function
    ''' <summary>
    ''' 批量验证邮箱
    ''' </summary>
    ''' <param name="Emails"></param>
    ''' <returns></returns>
    Public Function VerifyEmailsByMineLead(Emails As List(Of String)) As String
        If Emails.IsNull() OrElse Emails.Count = 0 Then CommonInvoke.Instance.GetReslut(False, "[邮箱错误]无法验证邮箱")
        Dim MutiThread As New Sy.Threading.MultiThread
        For Each Email In Emails
            MutiThread.AddTask(Sub()
                                   Dim Result As New Dictionary(Of String, Boolean)
                                   Dim url As String = $"https://api.minelead.io/v1/validate/?email={Email}"
                                   Dim html As String = Sy.Net.Factory.Http("http://httpproxy.miwaimao.com/").SetHeader("ProxyUrl", url).SetHeader("MineleadKey", "True").Get()
                                   Dim response As VerifyEmailResponse = VerifyEmailResponse.DeserializeSafety(html)
                                   If response.IsNull() OrElse response.status.IsNull() OrElse Not response.status = "success" Then
                                       Result.Add(Email, False)
                                   Else
                                       Result.Add(Email, response.webmail)
                                   End If
                                   ScriptManager.Instance.VerifyEmail(JsonObject.Serialize(Result))
                               End Sub)
        Next
        MutiThread.SetMaxThreads(10)
        MutiThread.SetAllTasked(Sub()

                                End Sub)
        MutiThread.Start()
        Return CommonInvoke.Instance.GetReslut(True, "")
    End Function

    ''' <summary>
    ''' 批量验证邮箱
    ''' </summary>
    ''' <param name="Emails"></param>
    ''' <returns></returns>
    Public Function VerifyEmails(Emails As List(Of String)) As String
        If Emails.IsNull() OrElse Emails.Count = 0 Then CommonInvoke.Instance.GetReslut(False, "[邮箱错误]无法验证邮箱")
        Dim domains = Emails.Select(Function(e)
                                        Dim split = e.Split((New Char() {"@"}), 2)
                                        Return If(split.Length < 2, "", split(1))
                                    End Function).Distinct().Where(Function(e) e.IsNotEmpty()).ToArray()
        If domains.Count = 0 Then CommonInvoke.Instance.GetReslut(False, "[邮箱错误]无法验证邮箱")

        Dim thread = New Thread(
            New ThreadStart(
            Async Sub()
                Dim tasks() = New Func(Of Task(Of Boolean))(domains.Length - 1) {}
                For i = 0 To domains.Length - 1
                    Dim num = i
                    tasks(i) = Function() ValidateEmailByMxCore(domains(num))
                Next
                Dim domainResult = Await TaskHelper.RunTasks(tasks, Environment.ProcessorCount)
                Debug.Assert(domainResult.Length, domains.Length)

                Dim domainDic = New Dictionary(Of String, Boolean)
                For i = 0 To domains.Length - 1
                    domainDic.Add(domains(i), domainResult(i))
                Next
                Dim Result As New Dictionary(Of String, Boolean)
                For Each email In Emails
                    Dim split = email.Split((New Char() {"@"}), 2)
                    Dim flag = False
                    If split.Length = 2 Then
                        domainDic.TryGetValue(split(1), flag)
                    End If

                    If Not Result.ContainsKey(email) Then
                        Result.Add(email, flag)
                    End If
                Next
                ScriptManager.Instance.VerifyEmail(JsonObject.Serialize(Result))
            End Sub))
        thread.Start()
        Return CommonInvoke.Instance.GetReslut(True, "")
    End Function

    Private _lookupClient As LookupClient

    Private Async Function ValidateEmailByMxCore(domain As String) As Task(Of Boolean)
        If _lookupClient.IsNull() Then _lookupClient = New LookupClient(New LookupClientOptions() With {.Timeout = TimeSpan.FromSeconds(2), .CacheFailedResults = True})
        Dim lookup = _lookupClient
        Dim flag = False
        Try
            Dim result = Await lookup.QueryAsync(domain, QueryType.MX, QueryClass.IN)
            If result.HasError Then
                Return False
            End If

            flag = result.Answers.MxRecords().Any()
        Catch ex As Exception

        End Try
        Dim obj = New With {domain, .mx = flag}
        ScriptManager.Instance.VerifyEmailLog(JsonObject.Serialize(obj))
        Return flag
    End Function

    ''' <summary>
    ''' 获取地图商家信息
    ''' </summary>
    ''' <param name="address"></param>
    ''' <param name="keywords"></param>
    ''' <returns></returns>
    Public Function GetMerchants(address As String, keywords As String) As String

        Sy.Threading.ThreadExecutor.Instance.Execute(Sub()
                                                         Try
                                                             Dim result = Helper.GetMerchants(address, keywords).Result
                                                             ScriptManager.Instance.GetMerchantsResult(result)
                                                         Catch ex As Exception
                                                             ScriptManager.Instance.GetMerchantsResult(ex.ToString())
                                                         End Try
                                                     End Sub)

        Return CommonInvoke.Instance.GetReslut(True, "")
    End Function

    Public Function SaveFile(json As String, fileType As String) As String
        Dim merchants = JsonSerializer.Deserialize(Of MerchantItem())(json, New JsonSerializerOptions() With {
                                                                      .PropertyNameCaseInsensitive = True})
        Dim result As String
        If fileType.Equals("csv", StringComparison.OrdinalIgnoreCase) Then
            result = SaveAsCsv(merchants)
        End If

        If result.IsNotWhiteSpace() Then
            Return CommonInvoke.Instance.GetReslut(False, result)
        End If

        Return CommonInvoke.Instance.GetReslut(True, "")
    End Function

    Private Function SaveAsCsv(data As MerchantItem()) As String
        '保存文件的名称
        Dim saveDlg = New SaveFileDialog With {
            .Title = "保存文件",
            .InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory),
            .FileName = Date.Now.ToString("yyyyMMddHHmm"),
            .Filter = "CSV 文件|*.csv",
            .RestoreDirectory = True
        }
        Dim saveName As String = ""
        If MainForm.Invoke(Function() saveDlg.ShowDialog()) = DialogResult.OK Then
            saveName = saveDlg.FileName
        End If
        If Not saveName.Length > 0 Then
            Return "文件名不能为空"
        End If
        '获取导出选项
        Try
            Dim fs = New FileStream(saveName, FileMode.Create, FileAccess.Write)
            Dim sw = New StreamWriter(fs, Encoding.UTF8)
            sw.WriteLine("名称,电话,网址,地址")

            For Each item In data
                Dim line = ""
                line &= Helper.FormatCsvField(item.Name) & ","
                line &= Helper.FormatCsvField(item.Phone) & ","
                line &= Helper.FormatCsvField(item.Website) & ","
                line &= Helper.FormatCsvField(item.Address)
                sw.WriteLine(line)
            Next

            sw.Close()
            fs.Close()

            Return ""
        Catch ex As Exception
            Return ex.ToString()
        End Try
    End Function
#End Region
End Class
